/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

#include <sstream>
#include <cstdio>
#include <cstring>
#include "common/type/date_type.h"
#include "common/value.h"
#include "common/lang/string.h"
#include "common/log/log.h"

// 日期存储为一个32位整数，格式为：YYYYMMDD
// 例如：2022-03-15将存储为20220315

int DateType::compare(const Value &left, const Value &right) const
{
  // 如果两边都是日期类型，直接比较整数值
  if (left.attr_type() == AttrType::DATES && right.attr_type() == AttrType::DATES) {
    int left_int = *(int *)left.data();
    int right_int = *(int *)right.data();

    if (left_int > right_int) {
      return 1;
    }
    if (left_int < right_int) {
      return -1;
    }
    return 0;
  }
  
  // 如果左边是字符串，右边是日期，则尝试将左边转换为日期后比较
  if (left.attr_type() == AttrType::CHARS && right.attr_type() == AttrType::DATES) {
    int32_t left_date;
    RC rc = parse_date(left.data(), left_date);
    if (rc != RC::SUCCESS) {
      LOG_WARN("Failed to convert string to date for comparison: %s", left.data());
      return INT32_MAX;
    }
    
    int right_date = *(int *)right.data();
    if (left_date > right_date) {
      return 1;
    }
    if (left_date < right_date) {
      return -1;
    }
    return 0;
  }
  
  // 如果左边是日期，右边是字符串，则尝试将右边转换为日期后比较
  if (left.attr_type() == AttrType::DATES && right.attr_type() == AttrType::CHARS) {
    int32_t right_date;
    RC rc = parse_date(right.data(), right_date);
    if (rc != RC::SUCCESS) {
      LOG_WARN("Failed to convert string to date for comparison: %s", right.data());
      return INT32_MAX;
    }
    
    int left_date = *(int *)left.data();
    if (left_date > right_date) {
      return 1;
    }
    if (left_date < right_date) {
      return -1;
    }
    return 0;
  }

  LOG_WARN("Not supported date comparation. left=%d, right=%d", left.attr_type(), right.attr_type());
  return INT32_MAX;
}

RC DateType::parse_date(const char *date_str, int32_t &date)
{
  if (date_str == nullptr) {
    return RC::INVALID_ARGUMENT;
  }

  size_t len = strlen(date_str);
  
  // 日期格式应至少有8个字符（如"2020-1-1"）
  if (len < 8) {
    return RC::INVALID_ARGUMENT;
  }

  // 查找第一个和第二个'-'的位置
  const char *first_dash = strchr(date_str, '-');
  if (first_dash == nullptr) {
    return RC::INVALID_ARGUMENT;
  }
  
  const char *second_dash = strchr(first_dash + 1, '-');
  if (second_dash == nullptr) {
    return RC::INVALID_ARGUMENT;
  }

  // 计算年、月、日的起始位置和长度
  const char *year_start = date_str;
  int year_len = first_dash - year_start;
  
  const char *month_start = first_dash + 1;
  int month_len = second_dash - month_start;
  
  const char *day_start = second_dash + 1;
  int day_len = len - (day_start - date_str);

  // 检查长度有效性
  if (year_len != 4 || month_len <= 0 || month_len > 2 || day_len <= 0 || day_len > 2) {
    return RC::INVALID_ARGUMENT;
  }

  // 提取年、月、日字符串
  char year_str[5], month_str[3], day_str[3];
  memcpy(year_str, year_start, year_len);
  year_str[year_len] = '\0';
  
  memcpy(month_str, month_start, month_len);
  month_str[month_len] = '\0';
  
  memcpy(day_str, day_start, day_len);
  day_str[day_len] = '\0';

  // 转换为数字
  int year = atoi(year_str);
  int month = atoi(month_str);
  int day = atoi(day_str);

  // 检查日期范围和有效性
  if (year < 1970 || year > 2038 || !is_valid_date(year, month, day)) {
    return RC::INVALID_ARGUMENT;
  }

  // 将日期转换为整数
  date = year * 10000 + month * 100 + day;
  return RC::SUCCESS;
}

void DateType::date_to_string(int32_t date, string &str)
{
  int year = date / 10000;
  int month = (date % 10000) / 100;
  int day = date % 100;

  char buf[16]; // 扩大缓冲区大小，避免格式化溢出
  sprintf(buf, "%04d-%02d-%02d", year, month, day);
  str = buf;
}

bool DateType::is_leap_year(int year)
{
  return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

bool DateType::is_valid_date(int year, int month, int day)
{
  if (month < 1 || month > 12 || day < 1) {
    return false;
  }

  static const int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  
  int max_days = days_in_month[month];
  if (month == 2 && is_leap_year(year)) {
    max_days = 29;
  }

  return day <= max_days;
}

RC DateType::set_value_from_str(Value &val, const string &data) const
{
  int32_t date_int;
  RC rc = parse_date(data.c_str(), date_int);
  if (rc != RC::SUCCESS) {
    return rc;
  }

  val.set_type(AttrType::DATES);
  val.set_data((char *)&date_int, sizeof(date_int));
  return RC::SUCCESS;
}

RC DateType::cast_to(const Value &val, AttrType type, Value &result) const
{
  switch (type) {
    case AttrType::DATES:
      result.set_type(AttrType::DATES);
      result.set_data(val.data(), val.length());
      return RC::SUCCESS;
    case AttrType::CHARS: {
      string date_str;
      int32_t date_int = *(int32_t *)val.data();
      date_to_string(date_int, date_str);
      result.set_type(AttrType::CHARS);
      result.set_data(date_str.c_str(), date_str.length());
      return RC::SUCCESS;
    }
    default:
      return RC::UNSUPPORTED;
  }
}

RC DateType::to_string(const Value &val, string &result) const
{
  if (val.attr_type() != AttrType::DATES) {
    LOG_WARN("Invalid date type conversion to string");
    return RC::INVALID_ARGUMENT;
  }

  int32_t date_int = *(int32_t *)val.data();
  date_to_string(date_int, result);
  return RC::SUCCESS;
} 